/*
 * @Author: yangzonglong
 * @Date: 2021-03-11 15:19:47
 * @version: v1.0.0
 * @Descripttion: 工具
 * @LastEditors: yangzonglong
 * @LastEditTime: 2023-01-07 05:13:42
 * @Auditor:
 */
import { units } from '@library';
import { controlDefOptions } from './config';
import { ControlProps, InputProps } from './interface';
import { FormItemProps } from 'antd/lib/form';
import { ControlType } from './config';

const defaultKeyArr = ['id'];
const defaultValueArr = [
  {
    formShowFlag: false,
    locales: { cn: 'id' },
    type: 'string',
  },
];
const fuzzyField = ['itfTypeCode', 'itfCode', 'itfTypeName', 'itfDesc'];
const order = [['createdAt', 'DESC']];

/**
 * 根据特定前辍生成随机字符串
 * @param {string} prefix  前辍字符串
 * @returns {string}
 */
export const createRandomStr = (prefix: string) =>
  prefix + '_' + Math.random().toString(32).substring(2);

/**
 * 生成控件默认配置
 * @param {string} type  控件类型
 * @returns {Object}
 */
export function createControlDefOptions(type: string, opts?: { name?: string; label?: string; id?: string; width?: string; }) {
  const options = JSON.parse(JSON.stringify(controlDefOptions[type] || {}));
  let children;

  if (options.formItemProps) {
    options.formItemProps.name = opts?.name || Math.random().toString(36).substring(2);
    opts?.label && (options.formItemProps.label = opts?.label);
    opts?.name && (options.formItemProps.style.width = (opts?.width || '25%'));
  }

  if (options.type === ControlType.TABLE) {
    options.name = opts?.name || Math.random().toString(36).substring(2);
    opts?.label && (options.title = opts?.label);
  }

  const id = opts?.id || createRandomStr(type);

  return {
    type: type,
    id: id,
    parentId: '',
    options,
    children
  };
}

/**
 * 获取模块下的模型
 * @param {string} name  模块名称
 * @returns {Array}
 */
export async function getModels(name: string) {
  try {
    const result = await units.server(`/bk/api/${name}/getModels`, {});
    return result.models || [];
  } catch (error) {
    return [];
  }
}

/**
 * 获取模型下的表
 * @param {string} name  模块名称
 * @param {string} module  模型名称
 * @returns {Array}
 */
export async function getModel(
  name: string,
  module: string
): Promise<{ label: string; value: string; }[]> {
  try {
    const result = await units.server(`/bk/api/${name}/${module}/getModel`, {});
    let res = {
      keyArr: Object.keys(result.attributes || {}).concat(defaultKeyArr),
      valueArr: Object.values(result.attributes || {}).concat(defaultValueArr),
    };

    return res?.keyArr?.map((item: string, index: number) => ({
      label: ((res?.valueArr[index] as any)?.locales?.cn ||
        (res?.valueArr[index] as any)?.comment ||
        (res?.valueArr[index] as any)?.cn || item || ''),
      value: item,
    }));
  } catch (error) {
    return [];
  }
}

/**
 * 获取公司级接口下的配置字段 用于lov的API类型 非标方法
 * @param {string} fuzzyValue  模块名称
 * @returns {Array}
 */
export async function companyModelItf(fuzzyValue: string): Promise<any[]> {
  try {
    const result = await units.server(`/bk/api/company/CompanyModelItf/find`, {
      fuzzyField,
      fuzzyValue,
      fuzzyQuery: !!fuzzyValue,
      order,
      where: {},
      include: [{ model: 'CompanyModelItfParam' }],
    });
    return result?.rows || [];
  } catch (error) {
    return [];
  }
}

// lov combox 可绑定的字段数组
export function getShowComponentsArray(list: ControlProps[], name: string) {
  const linkType = ['dataLink', 'dataLinkComBox'];
  let _list = list?.filter(
    (item) =>
      linkType.includes(item.type) &&
      name !== item?.options?.formItemProps?.name &&
      name !== item.options?.inputProps?.bindName
  );
  return _list?.map((item) => ({
    label: item.options?.formItemProps.label,
    value: item.options?.formItemProps.name,
  }));
}

// lov combox 绑定数组对应的字段
export function getBindmoduleName(list: ControlProps[], bindName: string) {
  let _temp = list.filter(
    (item) => item?.options?.formItemProps?.name === bindName
  );

  return Array.isArray(_temp?.[0]?.options?.inputProps?.filedShowName) ? _temp?.[0]?.options?.inputProps?.filedShowName : [{
    value: _temp?.[0]?.options?.inputProps?.filedShowName,
    label: _temp?.[0]?.options?.inputProps?.filedShowName,
  }, ...(_temp?.[0]?.options?.inputProps?.extraFieldName || [])];

}

const getTitle = (label: string) => {
  return label;
  // let _temp = label.split(' ')
  // return _temp.length && _temp.length >= 2 ? _temp[1] : _temp[0]
};

// 绑定双花括号语法返回对应的条件
export const replaceStr = (str: string, data: Object) => {
  if (!str) return;

  if (str.match(new RegExp('{{(\\S*)}}-{{(\\S*)}}'))) {
    const result: RegExpMatchArray = str.match(
      new RegExp('{{(\\S*)}}-{{(\\S*)}}')
    ) || ['', '', ''];
    const res = data[result[1]];
    return res?.[0]?.[result[2]] || null;
  } else if (str.match(new RegExp('{{(\\S*)}}'))) {
    const result = str.match(new RegExp('{{(\\S*)}}')) || ['', ''];
    return data?.[result[1]] || null;
  }
  return str;
};

export const textReplaceStr = (str: string, data: Object) => {
  data = data || {};
  if (!str) return '';
  if (str.indexOf('{{') < 0) return str;
  let temString = '';
  let arr = str.split('{{');
  arr.forEach(item => {
    if (item.indexOf('}}') > 0) {
      const _arr = item.split('}}');
      if (_arr.length === 3) {
        _arr[1] = _arr[2];
      }
      const key = _arr[0];
      let value = data[key] ?? '';
      temString += value + _arr[1];
    } else {
      temString += item;
    }
  });

  return temString;
};

// 获取条件
export const getQuery = (
  inputProps: any,
  formData: any
) => {
  let obj: any = { $or: [] };
  let screenCondition: any[] = inputProps.screenCondition || [];
  let screenConditionRules: any[] = inputProps.screenConditionRules || [];

  if (
    inputProps.bindName &&
    !(formData?.[inputProps.bindName])
  ) {
    return { where: obj };
  }

  screenCondition?.forEach((item) => {
    let _temp = {};
    item?.dataSource?.forEach((ele: any) => {
      let keyword = replaceStr(ele.keyword, formData);
      // if (!keyword) return
      if (keyword === 'true') keyword = true;
      if (keyword === 'false') keyword = false;

      _temp[ele.field] =
        ele.condition !== 'equal'
          ? {
            [ele.condition]:
              ele.condition === '$ne' || ele.condition === '$like'
                ? keyword
                : [keyword],
          }
          : keyword;
    });

    if (Object.keys(_temp).length) {
      obj.$or.push(_temp);
    }
  });

  const sendData = {
    value:
      Array.isArray(formData?.[inputProps.bindName]) ?
        formData?.[inputProps.bindName] : [formData?.[inputProps.bindName] || {}]
  };

  screenConditionRules?.forEach((item) => {
    let _temp = {};
    item?.dataSource?.forEach((ele: any) => {
      let _v = sendData.value?.reduce((all: any[], item: any) => {
        return item[ele.keyword] ? [...all, item[ele.keyword]] : [...all];
      }, []);

      if (!_v.length) return;

      _temp[ele.field] = {
        [ele.condition === 'equal' || ele.condition === '$like' ? '$in' : '$nin']: _v,
      };
    });
    if (Object.keys(_temp).length) {
      obj.$or.push(_temp);
    }
  });

  if (!screenCondition.length && !screenConditionRules.length) {
    if (obj.$or.length === 0) {
      delete obj.$or;
    }
  }

  return { where: obj };
};

export function getExtraObjByFiledShowName(
  data: object | object[],
  filedShowName: { value: string; label: string; }[],
  mapFileds: object
) {
  const stringValue = filedShowName.map((item) => item.value);
  const outwardObj = {};

  if (Array.isArray(data)) {
    return [
      data.map((item) => {
        let obj: object = {};
        for (let k in item) {
          if (item.hasOwnProperty(k) && stringValue.includes(k))
            obj[mapFileds[k] || k] = item[k];

          // 如果是数组向外平铺数据
          if (item.hasOwnProperty(k) && Array.isArray(item[k])) {
            outwardObj[mapFileds[k] || k] = item[k];
          }
        }
        obj['id'] = item['id'];
        return obj;
      }),
      outwardObj,
    ];
  } else {
    let obj: object = {};
    for (let k in data) {
      if (data.hasOwnProperty(k) && stringValue.includes(k)) obj[mapFileds[k] || k] = data[k];
    }
    obj['id'] = data['id'];
    return [obj, {}];
  }
}
// 获取 Modal条件xw
export function getModalOptions(
  formItemProps: FormItemProps,
  inputProps: InputProps,
  formData: Object,
  getCurrInterceptors?: Function
) {
  let canShow =
    (inputProps.modulesName || inputProps.modulesUrl) &&
    inputProps.serviceModuleCode &&
    inputProps.fieldNames &&
    inputProps.showFieldName;

  if (!canShow) {
    return {
      title: localStorage.i18nextLng === 'en' ? (formItemProps as any)?.labelEn : (formItemProps as any)?.label,
      columns: [],
      searchFields: [],
      searchFieldsText: [],
      url: '',
      fieldNames: { label: 'label', value: 'value' },
      query: {},
    };
  }

  // let _fieldsText = inputProps?.fieldNames?.filter(
  //   (item: any) => item.value === inputProps.showFieldName
  // )?.[0] || { label: '' }

  const searchFieldsText = inputProps.filedShowName?.map((item: any) => (localStorage.i18nextLng === 'en' ? item.labelEn : item.label) || item.label);
  const searchFields = inputProps.filedShowName?.map((item: any) => item.value);

  const query = getQuery(inputProps, formData);

  const options = {
    title: localStorage.i18nextLng === 'en' ? (formItemProps as any)?.labelEn : (formItemProps as any)?.label,
    columns: inputProps.filedShowName?.map((item: any) => ({
      dataIndex: item.value,
      title: getTitle((localStorage.i18nextLng === 'en' ? item.labelEn : item.label) || item.label),
      width: 150,
      tooltip: true,
      ellipsis: true,
      render: (text: string, record: any) =>
        record[item.value]
          ? typeof record[item.value] === 'object'
            ? JSON.stringify(record[item.value])
            : record[item.value]
          : '',
    })),
    searchFields,
    searchFieldsText,
    url:
      inputProps.serviceType === 'APP'
        ? `/bk/api/${inputProps.serviceModuleCode}/${inputProps.modulesName}/find`
        : inputProps.modulesUrl,
    fieldNames: { label: 'label', value: 'value' },
    query: (Array.isArray(inputProps.sortNames)) ? { ...query, order: inputProps.sortNames.map(ele => [ele.key, ele.sort]) } : query
  };

  const currInterceptors = getCurrInterceptors?.(options.url);

  if (currInterceptors?.set) {
    (options as any).handleQuerySet = currInterceptors?.set;
  }

  return options;
}

function handKeyword(keyword: string, data: any, record?: any) {
  if (keyword.includes('_RECORD_')) {
    return replaceStr(keyword.replace('_RECORD_.', ''), record);
  }
  return replaceStr(keyword, data);
}

// 获取Table条件
export const getTableQuery = (options: any, formData?: any, record?: any) => {
  let obj: any = { $or: [] };

  if (
    options.bindName &&
    !(formData?.[options.bindName] || record?.[options.bindName])
  ) {
    return { where: obj };
  }

  let screenCondition: any[] = options.screenCondition || [];
  let screenConditionRules: any[] = options.screenConditionRules || [];

  screenCondition?.forEach((item) => {
    let _temp = {};
    item?.dataSource?.forEach((ele: any) => {
      let keyword = handKeyword(ele.keyword, formData, record);

      if (keyword === 'true') keyword = true;
      if (keyword === 'false') keyword = false;

      _temp[ele.field] =
        ele.condition !== 'equal'
          ? {
            [ele.condition]:
              ele.condition === '$ne' || ele.condition === '$like'
                ? keyword
                : [keyword],
          }
          : keyword;
    });

    if (Object.keys(_temp).length) {
      obj.$or.push(_temp);
    }
  });

  let sendData: any = {};
  if (formData?.[options.bindName]) {
    sendData = Array.isArray(formData?.[options.bindName]) ? { value: formData?.[options.bindName] } : formData?.[options.bindName];
  } else {
    sendData = record;
  }

  screenConditionRules?.forEach((item) => {
    let _temp = {};
    item?.dataSource?.forEach((ele: any) => {
      const realRule =
        ele.condition === 'equal' || ele.condition === '$like' ? '$in' : '$nin';
      if (Array.isArray(sendData.value)) {
        _temp[ele.field] = {
          [realRule]: sendData.value?.reduce((all: any[], item: any) => {
            return item?.[ele.keyword] ? [...all, item[ele.keyword]] : [...all];
          }, []),
        };
      } else if (sendData[ele.keyword]) {
        const keyword = sendData[ele.keyword]?.split(' ');

        if (keyword.length >= 1) {
          _temp[ele.field] = {
            [realRule]: keyword,
          };
        }

      }
    });

    if (Object.keys(_temp).length) {
      obj.$or.push(_temp);
    }
  });

  if (obj.$or.length === 0) {
    delete obj.$or;
  }

  return { where: obj };
};

// 获取Table Modal条件
export const getTableModalOptions = (
  title: string,
  options: any,
  formData?: Object,
  record?: Object,
  getCurrInterceptors?: Function
) => {
  let canShow =
    (options?.modulesName || options?.modulesUrl) &&
    options?.serviceModuleCode &&
    options?.fieldNames &&
    options?.showFieldName;

  if (!canShow) {
    return {
      title,
      columns: [],
      searchFields: [],
      searchFieldsText: [],
      url: '',
      fieldNames: { label: 'label', value: 'value' },
      query: {},
    };
  }

  const searchFieldsText = options?.filedShowName?.map((item: any) => (localStorage.i18nextLng === 'en' ? item.labelEn : item.label) || item.label);
  const searchFields = options?.filedShowName?.map((item: any) => item.value);

  const query = getTableQuery(options, formData, record);

  const rtnData = {
    title: title,
    columns: options.filedShowName?.map((item: any) => ({
      dataIndex: item.value,
      width: 150,
      tooltip: true,
      title: (localStorage.i18nextLng === 'en' ? item.labelEn : item.label) || item.label,
      ellipsis: true,
      render: (text: string, record: any) =>
        record[item.value]
          ? typeof record[item.value] === 'object'
            ? JSON.stringify(record[item.value])
            : record[item.value]
          : '',
    })) || [],
    searchFields,
    searchFieldsText,
    url:
      options.serviceType === 'APP'
        ? `/bk/api/${options.serviceModuleCode}/${options.modulesName}/find`
        : options.modulesUrl,
    fieldNames: { label: 'label', value: 'value' },
    query: (Array.isArray(options.sortNames)) ? { ...query, order: options.sortNames.map((ele: any) => [ele.key, ele.sort]) } : query,
  };

  const currInterceptors = getCurrInterceptors?.(rtnData.url);
  if (currInterceptors?.set) rtnData.query = currInterceptors?.set(rtnData.query);

  return rtnData;
};

// 获取Table lov combox 可绑定的字段数组
export function getTableShowComponentsArray(options: {
  columns: any[];
  dataIndex: number;
  keyValue: string;
  list: any[];
}) {
  const linkType = ['dataLink', 'dataLinkCombox', 'dataLinkComBox'];

  let _dataObj: any = {};
  const { columns, list, dataIndex, keyValue } = options;

  let _list = columns?.filter(
    (item: any) =>
      linkType.includes(item.type) &&
      item.dataIndex !== dataIndex &&
      item.options?.bindName !== keyValue
  );

  let _outList = list?.filter((item: any) => linkType.includes(item.type));

  _list?.forEach((element: any) => {
    _dataObj[element.dataIndex!] = element?.options?.filedShowName || [];
  });

  _outList?.forEach((element: any) => {
    _dataObj[element.options.formItemProps.name] =
      element?.options?.inputProps.filedShowName || [];
  });

  let _filterList = _outList?.map((item: any) => ({
    label: item?.options.formItemProps.label,
    value: item?.options.formItemProps.name,
    id: item?.options.formItemProps.name,
  }));

  return {
    list: _list
      ?.map((item: any) => ({
        label: item?.title,
        value: item?.dataIndex,
        id: item?.key,
      }))
      .concat(_filterList),
    dataObj: _dataObj,
  };
}


export function flatControl(list: ControlProps[]) {
  const temp: ControlProps[] = [];

  const each = (arr: ControlProps[]) => {
    arr.forEach(item => {
      if (item.children) {
        if (item.children.length) {
          // console.log(item);
        }
        each(item.children);
        temp.push({ ...item, children: [] });
      } else {
        temp.push(item);
      }
    });
  };

  each(list);

  return temp;
}

// 将组件转成tree
export function controlToTree(list: ControlProps[]) {
  let arr: ControlProps[] = [];

  const controlMap: Record<string, ControlProps> = list.reduce((next, cur) => {
    next[cur.id] = cur;
    cur.children = [];
    return next;
  }, {});

  list.forEach(item => {
    const control: ControlProps = controlMap[item.id];

    if (control.id !== control.parentId && controlMap[control.parentId!]) {
      if (!controlMap[control.parentId!]) return;
      if (!controlMap[control.parentId!].children) controlMap[control.parentId!].children = [];
      return controlMap[control.parentId!].children!.push(control);
    }

    arr.push(control);
  });

  arr = arr.filter(item => {
    return !item.parentId;
  });

  return arr;
}

export const uniqueFunc = (arr: any[], uniId: string) => {
  const res = new Map();
  return arr.filter((item) => !res.has(item[uniId]) && res.set(item[uniId], 1));
};
